package com.ybl.store.backend.service.impl.deal;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ybl.store.backend.dao.entity.deal.DealProductDO;
import com.ybl.store.backend.dao.entity.deal.LogDealProductNumberDO;
import com.ybl.store.backend.dao.entity.deal.LogDealProductPaymentDO;
import com.ybl.store.backend.dao.entity.store.ProductDO;
import com.ybl.store.backend.dao.entity.store.StoreDO;
import com.ybl.store.backend.dao.entity.user.ClerkDO;
import com.ybl.store.backend.dao.entity.user.CustomerDO;
import com.ybl.store.backend.dao.mapper.deal.DealProductMapper;
import com.ybl.store.backend.dao.mapper.deal.LogDealProductNumberMapper;
import com.ybl.store.backend.dao.mapper.deal.LogDealProductPaymentMapper;
import com.ybl.store.backend.dao.mapper.store.ProductMapper;
import com.ybl.store.backend.dao.mapper.store.StoreMapper;
import com.ybl.store.backend.dao.mapper.user.ClerkMapper;
import com.ybl.store.backend.dao.mapper.user.CustomerMapper;
import com.ybl.store.backend.dto.UserInfoDTO;
import com.ybl.store.backend.dto.req.deal.DealProductSaveReqDTO;
import com.ybl.store.backend.dto.req.deal.DealProductUpdateReqDTO;
import com.ybl.store.backend.dto.resp.deal.DealProductExportRespDTO;
import com.ybl.store.backend.dto.resp.deal.DealProductPageRespDTO;
import com.ybl.store.backend.service.deal.DealProductService;
import com.ybl.store.common.constant.BanFlag;
import com.ybl.store.common.constant.DealStatus;
import com.ybl.store.common.constant.DelFlag;
import com.ybl.store.common.constant.UserPermission;
import com.ybl.store.common.context.UserContext;
import com.ybl.store.common.convention.errorcode.BaseErrorCode;
import com.ybl.store.common.convention.exception.ClientException;
import com.ybl.store.common.entity.ChildrenNameId;
import com.ybl.store.common.entity.ListRespDTO;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class DealProductServiceImpl extends ServiceImpl<DealProductMapper, DealProductDO> implements DealProductService {

    private final StoreMapper storeMapper;

    private final ClerkMapper clerkMapper;

    private final CustomerMapper customerMapper;

    private final ProductMapper productMapper;

    private final LogDealProductNumberMapper logDealProductNumberMapper;

    private final LogDealProductPaymentMapper logDealProductPaymentMapper;

    @Override
    public void saveDealProduct(DealProductSaveReqDTO requestParam) {
        checkIds(BeanUtil.toBean(requestParam, DealIds.class));

        DealProductDO dealProductDO = BeanUtil.toBean(requestParam, DealProductDO.class);
        dealProductDO.setCurrentNumber(0);
        dealProductDO.setCurrentPayment(new BigDecimal(0));
        dealProductDO.setDealStatus(DealStatus.inProgress);

        int result = baseMapper.insert(dealProductDO);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_SAVE_ERROR);
        }
    }

    @Override
    public void deleteDealProduct(Long id) {
        int result = baseMapper.deleteById(id);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_DELETE_ERROR);
        }

        // 删除数量关联
        {
            LambdaQueryWrapper<LogDealProductNumberDO> lambdaQueryWrapper = Wrappers.lambdaQuery(LogDealProductNumberDO.class)
                    .eq(LogDealProductNumberDO::getDealProductId, id);
            List<LogDealProductNumberDO> logDealProductNumberDOList = logDealProductNumberMapper.selectList(lambdaQueryWrapper);
            if (!logDealProductNumberDOList.isEmpty()) {
                throw new ClientException(BaseErrorCode.DEAL_PRODUCT_CANNOT_DELETE_ERROR);
            }
        }
        // 删除金额关联
        {
            LambdaQueryWrapper<LogDealProductPaymentDO> lambdaQueryWrapper = Wrappers.lambdaQuery(LogDealProductPaymentDO.class)
                    .eq(LogDealProductPaymentDO::getDealProductId, id);
            List<LogDealProductPaymentDO> logDealProductPaymentDOList = logDealProductPaymentMapper.selectList(lambdaQueryWrapper);
            if (!logDealProductPaymentDOList.isEmpty()) {
                throw new ClientException(BaseErrorCode.DEAL_PRODUCT_CANNOT_DELETE_ERROR);
            }
        }
    }

    @Override
    public void updateDealProduct(DealProductUpdateReqDTO requestParam) {
        checkIds(BeanUtil.toBean(requestParam, DealIds.class));

        DealProductDO dealProductDO = baseMapper.selectById(requestParam.getId());
        if (dealProductDO == null) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_NULL_ERROR);
        }
        if (dealProductDO.getCurrentNumber() > requestParam.getTotalNumber()) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_NUMBER_ERROR);
        }
        if (dealProductDO.getCurrentPayment().compareTo(requestParam.getTotalPayment()) > 0) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_PAYMENT_ERROR);
        }

        int result = baseMapper.updateById(BeanUtil.toBean(requestParam, DealProductDO.class));
        if (result < 1) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_UPDATE_ERROR);
        }
    }

    @Override
    public ListRespDTO<DealProductPageRespDTO> pageDealProduct(Integer pn, Integer ps, Long storeId, Long clerkId, Long customerId, Long productId, String startTime, String endTime, Integer dealStatus) {
        UserInfoDTO userInfoDTO = UserContext.get();
        if (!Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            storeId = userInfoDTO.getStoreId();
            clerkId = userInfoDTO.getId();
        }
        boolean timeCondition = Objects.nonNull(startTime) && Objects.nonNull(endTime);
//        if(timeCondition) {
//            Pattern p = Pattern.compile("T");
//            Matcher m = p.matcher(startTime);
//            int t=10;
//            if(m.find()) t=m.start();
//            startTime=startTime.substring(0,t);
//            Matcher n = p.matcher(endTime);
//            if(m.find()) t=n.start();
//            endTime=endTime.substring(0,t);
//        }
        Page<DealProductPageRespDTO> page = new Page<>(pn, ps);
        QueryWrapper<DealProductDO> queryWrapper = Wrappers.query(DealProductDO.class)
                .eq(Objects.nonNull(storeId), "deal.store_id", storeId)
                .eq(Objects.nonNull(clerkId), "deal.clerk_id", clerkId)
                .eq(Objects.nonNull(customerId), "deal.customer_id", customerId)
                .eq(Objects.nonNull(productId), "deal.product_id", productId)
//                .between(timeCondition, "deal.deal_time", startTime, endTime)
                .ge(timeCondition, "deal.deal_time", startTime)
                .le(timeCondition, "deal.deal_time", endTime)

                .eq(Objects.nonNull(dealStatus), "deal_status", dealStatus)
                .eq("deal.del_flag", 0)
                .orderByDesc("deal.deal_time");
        List<DealProductPageRespDTO> dealProductPageRespDTOList = baseMapper.pageDealProduct(page, queryWrapper);

        queryWrapper = Wrappers.query(DealProductDO.class)
                .eq(Objects.nonNull(storeId), "store_id", storeId)
                .eq(Objects.nonNull(clerkId), "clerk_id", clerkId)
                .eq(Objects.nonNull(customerId), "customer_id", customerId)
                .eq(Objects.nonNull(productId), "product_id", productId)
                .ge(timeCondition, "deal_time", startTime)
                .le(timeCondition, "deal_time", endTime)
//                .between(timeCondition, "deal_time", startTime, endTime)
                .eq(Objects.nonNull(dealStatus), "deal_status", dealStatus);
        Long total = baseMapper.selectCount(queryWrapper);

        return ListRespDTO.<DealProductPageRespDTO>builder()
                .total(total)
                .items(dealProductPageRespDTOList)
                .build();
    }


    @Override
    public List<DealProductExportRespDTO> export() {
        return baseMapper.export();
    }

    @Data
    static class DealIds {
        private Long storeId;
        private Long clerkId;
        private Long customerId;
        private Long productId;
    }
    @Override
    public List<ChildrenNameId> Cascader(){
        Long clerkId = null;
        UserInfoDTO userInfoDTO = UserContext.get();
        if (Objects.equals(userInfoDTO.getPermission(), UserPermission.MANAGER)) {
            clerkId = userInfoDTO.getId();
        }
        else if (Objects.equals(userInfoDTO.getPermission(), UserPermission.CLERK)) {
            clerkId = userInfoDTO.getId();

        }
        QueryWrapper<ClerkDO> queryWrapper = Wrappers.query(ClerkDO.class)
                .eq(Objects.nonNull(clerkId), "t_clerk.id", clerkId)
                .eq("t_clerk.del_flag", 0)
                .eq("t_clerk.ban_flag", 0);
        if (Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            queryWrapper = null;
        }
//                .orderByAsc(ClerkDO::getName);
//        return baseMapper.Cascader();

        return baseMapper.CascaderList(queryWrapper);



    }
    /**
     * 检查 ids 是否存在且合法
     *
     * @param dealIds 待检查的 ids
     */
    private void checkIds(DealIds dealIds) {
        UserInfoDTO userInfoDTO = UserContext.get();
        StoreDO storeDO = storeMapper.selectById(dealIds.getStoreId());
        ClerkDO clerkDO = clerkMapper.selectById(dealIds.getClerkId());
        CustomerDO customerDO = customerMapper.selectById(dealIds.getCustomerId());
        ProductDO productDO = productMapper.selectById(dealIds.getProductId());

        // 检查 ids 是否存在
        if (storeDO == null) {
            throw new ClientException(BaseErrorCode.STORE_NULL_ERROR);
        }
        if (clerkDO == null) {
            throw new ClientException(BaseErrorCode.CLERK_NULL_ERROR);
        }
        if (customerDO == null) {
            throw new ClientException(BaseErrorCode.CUSTOMER_NULL_ERROR);
        }
        if (productDO == null) {
            throw new ClientException(BaseErrorCode.PRODUCT_NULL_ERROR);
        }

        // 当前登录用户是否有权限
        if (!Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            if (!Objects.equals(clerkDO.getId(), userInfoDTO.getId())) {
                throw new ClientException(BaseErrorCode.CLIENT_UNAUTHORIZED_ERROR);
            }
        }

        // 检查 ids 是否合法
        if (!Objects.equals(clerkDO.getStoreId(), storeDO.getId()) ||
                !Objects.equals(customerDO.getClerkId(), clerkDO.getId()) ||
                !Objects.equals(productDO.getStoreId(), storeDO.getId())
        ) {
            throw new ClientException(BaseErrorCode.CLIENT_UNAUTHORIZED_ERROR);
        }
    }
}
